package com.richapp.launcher.utils;

import com.jack.netty.coder.tlv.TLVDecoder;
import com.jack.netty.coder.tlv.TLVEncoder;
import com.jack.netty.log.DefaultLogger;
import com.jack.netty.log.LoggerManager;
import com.jack.netty.tcp.client.TLVClient;
import com.jack.netty.tcp.client.TLVClientHandler;
import com.jack.netty.tcp.client.TLVClientListener;
import com.richapp.launcher.net.remote.RemoteClient;

import java.util.concurrent.TimeUnit;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;

/**
 * Created by dean on 2017/8/28 0028.
 */

public class DeanTLVClient {

    private String ip = "39.108.55.223";//岂控
//    private String ip = "120.26.199.77";//赛天
    private int port = 53656;
    private String clientName = "客户端";
    private int idleTimeRead = 5;
    private int idleTimeWrite = 5;
    private EventLoopGroup workergroup;
    private Bootstrap bootstrap;
    private TLVClientHandler clientHandler = null;
    private boolean manualCloseFlag = false;
    private boolean restartFlag = true;
    private TLVClientListener tlvClientListener = null;
    private int restartTime = 10;
    private boolean checkNetTimeOut = false;
    private int netTimeOut = 5000;
    public  boolean startIsSuccess=false;

    public DeanTLVClient() {

    }

    public void start() {
        manualCloseFlag=false;
        if(this.manualCloseFlag) {
            LoggerManager.getInstance().getiLogger().info(this.getClass(), "手动关闭" + this.clientName + "服务");
        } else {
            int timeoutCount = 0;

            while(!Tools.ping()) {
                try {
                    ++timeoutCount;
                    LoggerManager.getInstance().getiLogger().error(this.getClass(), "请检查网络是否可用,检查失败次数:" + timeoutCount);
//                    if (timeoutCount>10){
//                        RemoteClient.getInstance().stop();
//                        LoggerManager.getInstance().getiLogger().error(this.getClass(), "关闭远程服务，超时次数:" + timeoutCount);
//                    }
                    if(!this.restartFlag) {
                        LoggerManager.getInstance().getiLogger().warn(this.getClass(), "检测网络有问题且连接被设置不自动重连,关闭连接");
                        return;
                    }

                    if(this.checkNetTimeOut && timeoutCount > this.netTimeOut) {
                        LoggerManager.getInstance().getiLogger().warn(this.getClass(), "检测网络有问题且失败次数已超过" + this.netTimeOut + "次,关闭连接");
                        return;
                    }

                    Thread.sleep(20000L);
                } catch (Exception var8) {
                    LoggerManager.getInstance().getiLogger().error(this.getClass(), "网络检测暂停错误:" + var8.getMessage());
                }
            }

            try {
                this.workergroup = new NioEventLoopGroup();
                this.bootstrap = new Bootstrap();
                this.bootstrap.channel(NioSocketChannel.class);
                this.bootstrap.option(ChannelOption.SO_KEEPALIVE, Boolean.valueOf(true));
                this.bootstrap.option(ChannelOption.TCP_NODELAY, Boolean.valueOf(true));
                this.bootstrap.group(this.workergroup);
                this.bootstrap.handler(new LoggingHandler(LogLevel.INFO));
                this.clientHandler = new TLVClientHandler(this.tlvClientListener);
                this.bootstrap.handler(new ChannelInitializer() {
                    @Override
                    protected void initChannel(Channel channel) throws Exception {
                        channel.pipeline().addLast(new ChannelHandler[]{new IdleStateHandler(DeanTLVClient.this.idleTimeRead, DeanTLVClient.this.idleTimeWrite, 0)});
                        channel.pipeline().addLast(new ChannelHandler[]{new TLVEncoder()});
                        channel.pipeline().addLast(new ChannelHandler[]{new TLVDecoder()});
                        channel.pipeline().addLast(new ChannelHandler[]{DeanTLVClient.this.clientHandler});
                    }

//                    protected void initChannel(SocketChannel socketChannel) throws Exception {
//                        socketChannel.pipeline().addLast(new ChannelHandler[]{new IdleStateHandler(DeanTLVClient.this.idleTimeRead, DeanTLVClient.this.idleTimeWrite, 0)});
//                        socketChannel.pipeline().addLast(new ChannelHandler[]{new TLVEncoder()});
//                        socketChannel.pipeline().addLast(new ChannelHandler[]{new TLVDecoder()});
//                        socketChannel.pipeline().addLast(new ChannelHandler[]{DeanTLVClient.this.clientHandler});
//                    }
                });
                ChannelFuture e = this.bootstrap.connect(this.ip, this.port).sync();
                e.addListener(new ChannelFutureListener() {
                    public void operationComplete(ChannelFuture f) throws Exception {
                        if(f.isSuccess()) {
                            startIsSuccess=true;
                            LoggerManager.getInstance().getiLogger().info(this.getClass(), DeanTLVClient.this.clientName + "启动成功!");
                        } else if(DeanTLVClient.this.restartFlag) {
                            LoggerManager.getInstance().getiLogger().info(this.getClass(), DeanTLVClient.this.clientName + "启动失败,重启中...");
                            f.channel().eventLoop().schedule(new Runnable() {
                                public void run() {
                                    DeanTLVClient.this.start();
                                }
                            }, (long)DeanTLVClient.this.restartTime, TimeUnit.SECONDS);
                        } else {
                            LoggerManager.getInstance().getiLogger().error(this.getClass(), DeanTLVClient.this.clientName + "启动失败");
                            startIsSuccess=false;
                        }

                    }
                });
                e.channel().closeFuture().sync();
            } catch (Exception var7) {
                LoggerManager.getInstance().getiLogger().error(this.getClass(), this.clientName + "启动异常:" + var7.getMessage());
                this.restart();
//                if (timeoutCount>5){
//                    RemoteClient.getInstance().stop();
//                    LoggerManager.getInstance().getiLogger().error(this.getClass(), "关闭远程服务，超时次数..:" + timeoutCount);
//
//                }
            } finally {
                LoggerManager.getInstance().getiLogger().info(this.getClass(), this.clientName + "关闭前检测");
                this.workergroup.shutdownGracefully();
                this.workergroup = null;
                if(this.restartFlag) {
                    this.restart();
                }

            }

        }
    }

    private void restart() {
        try {
            Thread.sleep((long)(this.restartTime * 1000));
        } catch (InterruptedException var2) {
            LoggerManager.getInstance().getiLogger().error(this.getClass(), "重启暂停错误:" + var2.getMessage());
        }

        this.start();
    }

    public void stop() {
        this.manualCloseFlag = true;
        if(this.workergroup != null) {
            this.workergroup.shutdownGracefully();
        }

    }



    public boolean sendMessage(String message) {
        boolean sendFlag = false;
        if (RemoteClient.getInstance().isConnected()) {
            LoggerManager.getInstance().getiLogger().info(this.getClass(), "要发送的消息");
            if (this.clientHandler != null && this.clientHandler.getChannelHandlerContext() != null) {
                this.clientHandler.getChannelHandlerContext().writeAndFlush(message);
                sendFlag = true;
                LoggerManager.getInstance().getiLogger().info(this.getClass(), "发送消息到:" + this.clientHandler.getChannelHandlerContext().channel().id().asLongText());
            }
        }
        return sendFlag;
    }

    public String getServerId() {
        return this.clientHandler != null?this.clientHandler.getServerId():System.currentTimeMillis() + "";
    }

    public ChannelHandlerContext getServerChannelHandlerContext() {
        return this.clientHandler != null?this.clientHandler.getChannelHandlerContext():null;
    }

    public String getIp() {
        return this.ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public int getPort() {
        return this.port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getClientName() {
        return this.clientName;
    }

    public void setClientName(String clientName) {
        this.clientName = clientName;
    }

    public int getIdleTimeRead() {
        return this.idleTimeRead;
    }

    public void setIdleTimeRead(int idleTimeRead) {
        this.idleTimeRead = idleTimeRead;
    }

    public int getIdleTimeWrite() {
        return this.idleTimeWrite;
    }

    public void setIdleTimeWrite(int idleTimeWrite) {
        this.idleTimeWrite = idleTimeWrite;
    }

    public boolean isManualCloseFlag() {
        return this.manualCloseFlag;
    }

    public void setManualCloseFlag(boolean manualCloseFlag) {
        this.manualCloseFlag = manualCloseFlag;
    }

    public boolean isRestartFlag() {
        return this.restartFlag;
    }

    public void setRestartFlag(boolean restartFlag) {
        this.restartFlag = restartFlag;
    }

    public TLVClientListener getTlvClientListener() {
        return this.tlvClientListener;
    }

    public void setTlvClientListener(TLVClientListener tlvClientListener) {
        this.tlvClientListener = tlvClientListener;
    }

    public boolean isConnected() {
        return this.clientHandler != null?this.clientHandler.isConnectedFlag():false;
    }

    public int getRestartTime() {
        return this.restartTime;
    }

    public void setRestartTime(int restartTime) {
        this.restartTime = restartTime;
    }

    public int getNetTimeOut() {
        return this.netTimeOut;
    }

    public void setNetTimeOut(int netTimeOut) {
        this.netTimeOut = netTimeOut;
    }

    public boolean isCheckNetTimeOut() {
        return this.checkNetTimeOut;
    }

    public void setCheckNetTimeOut(boolean checkNetTimeOut) {
        this.checkNetTimeOut = checkNetTimeOut;
    }

    public boolean isStartIsSuccess() {
        return startIsSuccess;
    }

    public void setStartIsSuccess(boolean startIsSuccess) {
        this.startIsSuccess = startIsSuccess;
    }

    public static void main(String[] args) {
        LoggerManager.getInstance().setiLogger(new DefaultLogger());
        byte clientCount = 1;

        for(int i = 0; i < clientCount; ++i) {
            final TLVClient client = new TLVClient();
            client.setIp("127.0.0.1");
            client.setPort('톕');
            client.setTlvClientListener(new TLVClientListener() {
                public void onConnect(String serverId) {
                    client.sendMessage("{\"currentBoxCpuId\":\"4441551632315735c5000136fe7d0409\",\"email\":\"12435678@qq.com\",\"id\":0,\"idCard\":\"1234567\",\"nickName\":\"ok\",\"password\":\"222\",\"phone\":\"180163073913\",\"phoneName\":\"MI NOTE LTE\",\"phoneType\":\"android\",\"phoneUid\":\"867451024676424\",\"type\":1,\"userName\":\"ok\"}");
                }

                public void onDisconnect(String serverId) {
                }

                public void onMessage(String serverId, String message) {
                    client.sendMessage("{\n  \"currentBoxCpuId\": \"4441551632315735c5000136fe7d0409\", \n  \"data\": {\n    \"actionList\": [\n      {\n        \"actionDeviceOrder\": 0, \n        \"actionType\": 0, \n        \"alarmFlag\": false, \n        \"boxCpuId\": \"444155163231573501000136d1940008\", \n        \"checkTime\": 0, \n        \"curtainProgress\": 0, \n        \"delayTime\": 5000, \n        \"deviceId\": \"03\", \n        \"deviceName\": \"00|灯座|1\", \n        \"deviceNumber\": \"0001\", \n        \"deviceStatus\": \"FF\", \n        \"flashFlag\": false, \n        \"id\": 0, \n        \"imageId\": 0, \n        \"isSelect\": 0, \n        \"type\": 0, \n        \"way\": \"01\"\n      }, \n      {\n        \"actionDeviceOrder\": 1, \n        \"actionType\": 0, \n        \"alarmFlag\": false, \n        \"boxCpuId\": \"444155163231573501000136d1940008\", \n        \"checkTime\": 0, \n        \"curtainProgress\": 0, \n        \"delayTime\": 0, \n        \"deviceId\": \"03\", \n        \"deviceName\": \"00|灯座|444fftf总\", \n        \"deviceNumber\": \"0004\", \n        \"deviceStatus\": \"FF\", \n        \"flashFlag\": false, \n        \"id\": 0, \n        \"imageId\": 0, \n        \"isSelect\": 0, \n        \"type\": 0, \n        \"way\": \"01\"\n      }\n    ], \n    \"chooseAll\": \"true\", \n    \"conditionSensingList\": [ ], \n    \"conditionStateList\": [ ], \n    \"conditionTimeList\": [ ], \n    \"currentBoxCpuId\": \"4441551632315735c5000136fe7d0409\", \n    \"openFlag\": \"\", \n    \"sceneIcon\": \"qj16.png\", \n    \"sceneName\": \"523\", \n    \"triggerType\": 0, \n    \"type\": 31, \n    \"userName\": \"ok\"\n  }, \n  \"type\": 31, \n  \"userName\": \"ok\"\n}");
                }
            });
            (new Thread(new Runnable() {
                public void run() {
                    client.start();
                }
            })).start();
        }

    }

}
